package com.hzit.config;

import com.hzit.filter.HzitAuthFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * springSecurity安全框架认证配置
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class HzitSpringSecurityConfig  {
	@Autowired
	private AuthenticationEntryPoint authenticationEntryPoint;
	@Autowired
	private AccessDeniedHandler accessDeniedHandler;
	@Autowired
	private UserDetailsService  userDetailsService;
	@Autowired
	private HzitAuthFilter authFilter;
	//1. 在这里进行配置springSecurity
	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http.csrf().disable()
				//1.1 原来使用的是session+cookie机制来传递数据，现在禁用它，使用的是token机制
			  .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
			  .and()
			   //1.2 任何其它请求需要认证才能访问
			  .authorizeRequests()
			  .anyRequest().authenticated()
			  //1.3 配置认证失败处理器和授权失败处理器
		      .and()
			  .exceptionHandling()
			  .authenticationEntryPoint(authenticationEntryPoint)           // 认证失败处理器
			  .accessDeniedHandler(accessDeniedHandler)                     // 授权失败处理器
			  .and()
			  //1.4 指定用户认证的服务接口
			  .userDetailsService(userDetailsService)
			  //1.5 在指定过滤器前添加过滤器完成授权操作
			  .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);

		return http.build();
	}

	//2. 配置要忽略的请求资源路径
	@Bean
	public WebSecurityCustomizer webSecurityCustomizer() {
		return web -> web.ignoring().mvcMatchers("/user/login");
	}

	//3. 配置认证管理器
	@Bean
	public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
		return configuration.getAuthenticationManager();
	}
	//4. 配置密码加密器
	@Bean
	public PasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}
}
